package com.umeox.auto_update

import android.os.Handler
import android.os.Looper
import com.umeox.base.CloseableCoroutineScope
import com.umeox.logger.UMLogger
import com.umeox.sdk_ring.RingOTAUpgradeListener
import com.umeox.sdk_ring.UMRingSdk
import com.umeox.sdk_ring.protocol.IEmptyAppProtocol
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.File
import java.util.Date
import java.util.TimeZone
import kotlin.math.abs

private const val TAG = "AutoUpdateDeviceProxy"

class AutoUpdateDeviceProxy(val device: AutoUpdateDevice) : IEmptyAppProtocol,
    RingOTAUpgradeListener {

    companion object {
        const val STATE_IDLE = 0
        const val STATE_RUN = 1
        const val STATE_SUCCESS = 2
        const val STATE_ERROR = 3
    }

    /**
     * 设备携程空间
     */
    private val deviceScope = CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)

    private val record = arrayListOf<String>()

    private var progress = 0

    private val handler = Handler(Looper.getMainLooper())

    private val versionTimeoutCheckTask = Runnable {
        record.add("版本获取超时")
        UMLogger.d(TAG, "设备${device.mac} 版本获取超时")
        onFailed("版本获取超时")
    }

    private val otaSuccessCheckTimeoutCheckTask = Runnable {
        record.add("版本升级检验超时")
        UMLogger.d(TAG, "设备${device.mac} 版本升级检验超时")
        DeviceSearchManager.waitReconnectDeviceList.remove(device.mac)
        onFailed("版本升级检验超时")
    }

    private val otaTimeoutCheckTask = Runnable {
        record.add("OTA升级超时")
        UMLogger.d(TAG, "设备${device.mac} OTA升级超时")
        onFailed("OTA升级超时")
    }

    /**
     * 当前设备状态
     */
    var state = STATE_IDLE

    fun getDeviceInfo(): String {
        val info = record.joinToString("->")
        return if (progress == 0) {
            info
        } else {
            "$info /n  当前升级进度：% $progress"
        }
    }

    private val ringProxy by lazy {
        UMRingSdk.createRingProxy(device.mac).apply {
            addAppProtocolObserver(this@AutoUpdateDeviceProxy)
        }
    }

    fun startTask() {
        record.add("开始任务")
        UMLogger.d(TAG, "设备${device.mac} 开始任务")
        ringProxy.connectDevice()
    }

    override fun onConnectTimeout() {
        record.add("连接超时")
        UMLogger.d(TAG, "设备${device.mac} 设备连接超时")
        onFailed("连接超时")
    }

    override fun onConnected() {
        record.add("连接成功")
        UMLogger.d(TAG, "设备${device.mac}连接成功")
        deviceScope.launch {
            delay(6000)
            record.add("获取版本")
            UMLogger.d(TAG, "设备${device.mac}发送获取版本指令")
            ringProxy.getDeviceBatteryPower()

            handler.postDelayed(versionTimeoutCheckTask, 15 * 1000)
            state = STATE_RUN
            AutoUpdateManager.notifyStatusChange()
        }
    }

    override fun requestTimeSync() {
        ringProxy.syncCurrentTimeAndTimeFormat(null, null, true, getCurrentTimeZone())
    }

    /**
     * 可简化计算过程 为了方便理解 没有简化
     */
    private fun getCurrentTimeZone(): Double {
        val now = Date()
        val zone = TimeZone.getDefault()
        val id = zone.id
        val timeZone1 = TimeZone.getTimeZone(id)
        val timeZone2 = TimeZone.getTimeZone("UTC")

        val currentOffsetFromUTC = if (timeZone1.inDaylightTime(now)) {
            timeZone1.dstSavings + timeZone1.rawOffset
        } else {
            0 + timeZone1.rawOffset
        }

        val serverOffsetFromUTC = if (timeZone2.inDaylightTime(now)) {
            timeZone2.dstSavings + timeZone2.rawOffset
        } else {
            0 + timeZone2.rawOffset
        }

        val isNegativeNumber = currentOffsetFromUTC < 0

        val secondOffset = abs(abs(serverOffsetFromUTC) - currentOffsetFromUTC) / 1000
        val hour = secondOffset / 3600
        val minute = secondOffset % 3600 / 60
        return if (isNegativeNumber) {
            -1.0 * (hour + minute / 60.0)
        } else {
            hour + minute / 60.0
        }
    }

    override fun onBatteryPowerCallback(
        status: String,
        bat: String,
        version: String,
        versionName: String,
        buildTime: String
    ) {
        record.add(" version = $version   versionName = $versionName")
        UMLogger.d(TAG, "设备${device.mac} version = $version   versionName = $versionName")
        handler.removeCallbacks(versionTimeoutCheckTask)
        handler.removeCallbacks(otaSuccessCheckTimeoutCheckTask)

        if (versionName == AutoUpdateManager.getTarVersion()) {
            onSuccess()
            return
        } else {
            if (!AutoUpdateManager.isSupport(versionName)) {
                onUnSupport()
                return
            }
            startOTA()
        }
    }

    private fun onSuccess() {
        //升级成功
        record.add("已是目标版本")
        DeviceSearchManager.processedDeviceList.add(device.mac)
        DeviceSearchManager.waitReconnectDeviceList.remove(device.mac)
        UMLogger.d(TAG, "设备${device.mac} 已是目标版本，无需升级，提示并关机")
        deviceScope.launch {
            delay(2 * 1000)
            ringProxy.startFindDevice()
            delay(12 * 1000)
            ringProxy.shutdown()
            delay(3000)
            ringProxy.destroy()
            delay(1000)
            state = STATE_SUCCESS
            AutoUpdateManager.notifyStatusChange()
            AutoUpdateManager.requestDeviceJoin("${device.mac} - 升级成功")
        }
    }

    private fun onUnSupport() {
        record.add("不支持升级的设备版本")
        UMLogger.d(TAG, "设备${device.mac} 是不支持升级的设备版本")
        DeviceSearchManager.processedDeviceList.add(device.mac)
        onFailed("不支持升级的设备版本")
    }

    private fun startOTA() {
        val otaTargetFile = AutoUpdateManager.getOTATargetFile()
        handler.postDelayed(otaTimeoutCheckTask, 10 * 60 * 1000)
        ringProxy.startOTAUpgrade(File(otaTargetFile), false, this)
    }

    private fun onFailed(reason: String) {
        deviceScope.launch(Dispatchers.Main) {
            state = STATE_ERROR
            AutoUpdateManager.notifyStatusChange()
            delay(2000)
            record.add("销毁")
            UMLogger.d(TAG, "销毁设备${device.mac}")
            ringProxy.destroy()
            delay(5000)
            AutoUpdateManager.requestDeviceJoin("${device.mac} - 升级失败 - $reason")
        }
    }

    /**
     * 升级过程不处理
     */
    override fun upgradeProgress(progress: Int) {
        this.progress = progress
    }

    /**
     * 更新开始 不处理
     */
    override fun upgradeStart() {
        record.add("升级开始")
        UMLogger.d(TAG, "设备${device.mac} 升级开始")
    }


    override fun upgradeSuccessful() {
        record.add("升级成功")
        DeviceSearchManager.waitReconnectDeviceList.add(device.mac)
        UMLogger.d(TAG, "设备${device.mac} 升级成功")
        handler.removeCallbacks(otaTimeoutCheckTask)
        handler.postDelayed(otaSuccessCheckTimeoutCheckTask, 20 * 1000L)
    }

    override fun upgradeFail() {
        record.add("升级失败")
        UMLogger.d(TAG, "设备${device.mac} 升级失败")
        handler.removeCallbacks(otaTimeoutCheckTask)
        onFailed("升级过程失败")
    }
}